#pragma once

#ifndef BLOBTRACKER_H
#define BLOBTRACKER_H

#include "cvhead.h"
#include "TouchData.h"
#include "vector2d.h"
#include "rect2d.h"
#include <vector>

#define HISTORY_FRAMES	10

class Blob
{
public:
	vector2df last_center;
	vector2df center;
	float area;
	rect2df box;
	float angle;
	float weight;
	int tagID;		// for fiducal markers. 0 = regular touchpoint.

	Blob();
	~Blob();
};

class Finger : public Blob
{
public:
	Finger() 
	{
		ID = -1;
		markedForDeletion = false;
		framesLeft = 0;
	}

	Finger(const Blob &b)
	{
		ID = -1;
		center = b.center;
		area = b.area;
		box = b.box;
		angle = b.angle;
	}

	int getLowestError()
	{
		int best=-1;
		float best_v=99999.0f;

		for(unsigned int i=0; i<error.size(); i++)
		{
			if(error[i] < best_v)
			{
				best = i;
				best_v = error[i];
			}
		}

		return best;
	};

	TouchData getTouchData()
	{
		TouchData data;
		data.ID = ID;
		data.lastX = last_center.X;
		data.lastY = last_center.Y;
		data.X = center.X;
		data.Y = center.Y;

		data.angle = angle;
		data.width = box.getWidth();
		data.height = box.getHeight();
		data.area = data.width*data.height;

		data.dX = delta.X;
		data.dY = delta.Y;

		data.tagID = tagID;

		return data;
	};

	int ID;

	vector2df delta;
	vector2df predictedPos;

	vector2df displacement;

	float deltaArea;

	bool markedForDeletion;
	int framesLeft;

	std::vector<float> error;
	std::vector<int> closest;		// ID's of the closest points, sorted..
};

class BlobTracker
{

private:
	size_t numcheck;
	int extraIDs;
	int currentID;
	int ghost_frames;

	int reject_min;
	int reject_max;
	int reject_distance;
	float min_displacement;
	std::vector<Blob> blob_list;
	//the following algorithms are from touch-lib
	void find_blob(IplImage* img);
	void track_blob(void);
	void gather_events(void);
	void cal_matrix(int);
	bool check_valid(int);
	bool check_valid_new(int);
	float getError(Finger &old, Finger &cur);
	
	void do_touch(TouchData);
	void do_update(TouchData);
	void do_untouch(TouchData);

public:
	std::vector<Finger> current;
	std::vector<std::vector<int> > matrix;
	std::vector<int> ids;
	std::vector<std::vector<Finger> > history;
	std::vector<TouchData>	vec_event;
	std::vector<TouchData> process(IplImage* img);
	BlobTracker(void);
	~BlobTracker(void);

};

#endif